/*
 * =====================================================================================
 *
 *        Package:  kissdb
 *       Filename:  kissdb.go
 *
 *    Description:  go-kissdb
 *
 *        Created:  7/2/18 9:11 PM
 *
 *         Author:  hacklog
 *            URL:  http://80x86.io
 *
 * =====================================================================================
 */
package kissdb

/*
#include <stdlib.h>
#include "kissdb.h"
#cgo LDFLAGS: -L.
*/
import "C"
import (
	"log"
	"unsafe"
)

var IS_DEBUG = false

const (
	/**
	* Open mode: read only
	*/
	KISSDB_OPEN_MODE_RDONLY = C.KISSDB_OPEN_MODE_RDONLY

	/**
	 * Open mode: read/write
	 */
	KISSDB_OPEN_MODE_RDWR = C.KISSDB_OPEN_MODE_RDWR

	/**
	 * Open mode: read/write, create if doesn't exist
	 */
	KISSDB_OPEN_MODE_RWCREAT = C.KISSDB_OPEN_MODE_RWCREAT

	/**
	 * Open mode: truncate database, open for reading and writing
	 */
	KISSDB_OPEN_MODE_RWREPLACE = C.KISSDB_OPEN_MODE_RWREPLACE
)

func GetVersion() int {
	return C.KISSDB_VERSION
}

func New() *C.KISSDB {
	db := &C.KISSDB{}
	return db
}

const COK = 0

func DbgPrintf(fmt string, val ... interface{}) {
	if IS_DEBUG {
		log.Printf(fmt, val...)
	}
}

func Open(db *C.KISSDB, path string, mode int, hash_table_size, key_size, value_size uint32) bool {
	cpath := C.CString(path)
	rs := C.KISSDB_open(db, cpath, C.int(mode), C.ulong(hash_table_size), C.ulong(key_size), C.ulong(value_size))
	C.free(unsafe.Pointer(cpath))
	//DbgPrintf("C.KISSDB_open ret:%d\n", rs)
	if rs == COK {
		return true
	}
	return false
}

func Close(db *C.KISSDB) {
	C.KISSDB_close(db)
}

func Put(db *C.KISSDB, key string, value string) bool {
	ckey := unsafe.Pointer(C.CString(key))
	cvalue := unsafe.Pointer(C.CString(value))
	rs := C.KISSDB_put(db, ckey, cvalue)
	DbgPrintf("C.Put key:%s, val:%s, ret:%d\n", key,value, rs)
	C.free(unsafe.Pointer(ckey))
	C.free(unsafe.Pointer(cvalue))
	if rs == COK {
		return true
	}
	return false
}

func Get(db *C.KISSDB, key string, value *string) bool {
	ckey := unsafe.Pointer(C.CString(key))
	var tempVal = C.calloc(db.value_size, 1)
	if tempVal == C.NULL {
		DbgPrintf("Get C.calloc failed.")
		return false
	}
	rs := C.KISSDB_get(db, ckey, tempVal)
	*value = C.GoString((*C.char)(tempVal))
	DbgPrintf("Get key:%s, cvalue:%#v, ret:%d\n", key, C.GoString((*C.char)(tempVal)), rs)
	C.free(unsafe.Pointer(ckey))
	C.free(tempVal)
	if rs == COK {
		return true
	}
	return false
}
